/*
  将下面异步代码使用 Promise 的方法改进
  尽量用看上去像同步代码的方式
  setTimeout(function () {
    var a = 'hello'
    setTimeout(function () {
      var b = 'lagou'
      setTimeout(function () {
        var c = 'I ♥ U'
        console.log(a + b +c)
      }, 10)
    }, 10)
  }, 10)
*/

/*=============================================
=                    Promise                  =
=============================================*/

/**
 * @description: 使用 Promise 实现异步代码
 */
new Promise((resolve, reject) => {
  setTimeout(() => {
    const a = 'hello';
    resolve(a);
  }, 10);
})
  .then((a) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        const b = a + 'lagou';
        resolve(b);
      }, 10);
    });
  })
  .then((b) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        const c = b + 'I ♥ U';
        resolve(c);
      }, 10);
    });
  })
  .then((c) => {
    console.log(c);
  });

/*=============================================
=                    Generator                =
=============================================*/

/**
 * @description: 使用 Generator 实现
 */

function* generateTask() {
  const a = yield new Promise((resolve, reject) => {
    setTimeout(() => {
      const a = 'hello';
      resolve(a);
    }, 10);
  });
  const b = yield new Promise((resolve, reject) => {
    setTimeout(() => {
      const b = 'lagou';
      resolve(b);
    }, 10);
  });
  const c = yield new Promise((resolve, reject) => {
    setTimeout(() => {
      const c = 'I ♥ U';
      resolve(c);
    }, 10);
  });
  return a + b + c;
}

/**
 * @description: Generator执行器
 * @param {Function} Generator函数
 * @return {Promise} Promise
 */
function asyncToGenerator(generatorFunc) {
  return function () {
    const gen = generatorFunc.apply(this, arguments);
    return new Promise((resolve, reject) => {
      function step(key, arg) {
        let generatorResult;
        try {
          generatorResult = gen[key](arg);
        } catch (error) {
          return reject(error);
        }
        const { value, done } = generatorResult;
        if (done) {
          return resolve(value);
        } else {
          return Promise.resolve(value).then(
            (val) => step('next', val),
            (err) => step('throw', err)
          );
        }
      }
      step('next');
    });
  };
}

asyncToGenerator(generateTask)().then((result) => {
  console.log(result);
});

/*=============================================
=                      async                  =
=============================================*/

/**
 * @description: 使用 async 实现异步代码
 */

(async function asyncTask() {
  const a = await new Promise((resolve, reject) => {
    setTimeout(() => {
      const a = 'hello';
      resolve(a);
    }, 10);
  });
  const b = await new Promise((resolve, reject) => {
    setTimeout(() => {
      const b = 'lagou';
      resolve(b);
    }, 10);
  });
  const c = await new Promise((resolve, reject) => {
    setTimeout(() => {
      const c = 'I ♥ U';
      resolve(c);
    }, 10);
  });
  console.log(a + b + c);
  return a + b + c;
})();
